

#include <chprintf.h>
#include "shell.h"
#include <string.h>
#include <ctype.h>
#include "chprintf.h"
#include <iostream.h>
//#include "utils.h"


static const Shell_Cmd_t *_cmdList;

void Shell_Init(const Shell_Cmd_t cmdList[])
{
    _cmdList = cmdList;

//    Serial_SetCallbacks(STDIO_SERIAL, _OnTxBegin, _OnTxCompltet, _LineSignal);
//    printf("Simple Shell Launch\nshell>");
}

static int _IsSpace(char c)
{
    if((c == ' ') || (c == '\f') || (c == '\n') || (c == '\r') || (c == '\t')
            || (c == '\v'))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

#if 0
static void _RemoveTaillSpace(char *str)
{
    unsigned int i;

    i = strlen(str) - 1;
    while(_IsSpace(str[i]))
    {
        str[i] = '\0';
        if(i == 0)
        {
            break;
        }

        i--;
    }
}
#endif

static int _CmdStringSplit(int argcMax, char *str, char **argv)
{
    int argc;
    bool argStarted;

    argc = 0;
    argStarted = FALSE;
    for(argc = 0; argc < argcMax; str++)
    {
        if(*str == '\0')
        {
            if(argStarted)
            {
                argc += 1;
            }

            break;
        }

        if(_IsSpace(*str))
        {
            if(argStarted)
            {
                *str = '\0';
                argc += 1;
                argStarted = FALSE;
            }
        }
        else
        {
            if(! argStarted)
            {
                argv[argc] = str;
                argStarted = TRUE;
            }
        }
    }

    return argc;
}

static void _CmdShell(Stream_t *stream, char *line, char till)
{
    int argc;
    char *argv[16];
    unsigned int i;
//    bool cmdExist;

//    chprintf((BaseStream *) stream, "cmd = %s\r\n", buf);
    argc = _CmdStringSplit(ARRAY_SIZE(argv), line, argv);
    if(argc > 0)
    {
//        cmdExist = FALSE;
        for(i = 0; _cmdList[i].name[0] != '\0'; i++)
        {
            if(strcmp(argv[0], _cmdList[i].name) == 0)
            {
//                cmdExist = TRUE;
                CALL_BACK(_cmdList[i].callback, stream, argc, argv);
                break;
            }
        }

//        if(! cmdExist)
//        {
//            chprintf(stream, "Unknown Cmd: %s\r\n", argv[0]);
//        }
    }

//    chprintf(stream, "\r\nshell> ");
}

void Shell_OnLine(MsgQueue_Msg_t *msg)
{
    char buf[64];
    Shell_LineInMsg_t *lineMsg;

    lineMsg = (Shell_LineInMsg_t *) msg->data;

    if (Stream_RecvUntil(lineMsg->stream, buf, sizeof(buf), lineMsg->till) == -1)
    {
//        chprintf(lineMsg->stream, "FAIL");
        return;
    }

    _CmdShell(lineMsg->stream, buf, '\n');
}

int Shell_Test(Stream_t *stream, int argc, char *argv[])
{
    int i;

    chprintf(stream, "Shell Test:\r\n");
    for(i = 0; i < argc; i++)
    {
        chprintf(stream, "arg %d: %s\r\n", i, argv[i]);
    }

    return 0;
}

int Shell_Help(Stream_t *stream, int argc, char *argv[])
{
    unsigned int i;

    for(i = 0; _cmdList[i].name[0] != '\0'; i++)
    {
        chprintf(stream, "%s ", _cmdList[i].name);
    }

    chprintf(stream, "\r\n");

    return 0;
}
